כפי שהשם אומר mysqli = mysql Improved זוהי ספריה משופרת לעבודה עם mysql. הכננו לכם רשימה של שיפורים — 7 סיבות למה להשתמש דווקא בה.
למה mysqli?
1. שיפור של כ-20% ביצועים
2. ממשק תפעול מונחה עצמים (object oriented)
3. תמיכה בשאילתות מוכנות מראש (prepared statements)
4. תמיכה בשאילתות מרובות (multiple statements)
5. תמיכה בטראנזקציות
6. כלים משופרים לניפוי (דיבאג) שגיאות
7. תמיכה בפרוצדורות מסד (stored procedures)
I. התקנת mysqli
סביר להניח שחברת האחסון שלכם כבר תומכת בהרחבה mysqli
ויהיה צורך להפעיל אותה על המחשב הביתי שלכם.
1. פתחו את קובץ ההדגרות php.ini
ניתן להיעזר בכתבה איך למצוא את קובץ ההגדרות php.ini
2. מצאו בקובץ את המילה mysqli
החיפוש יוביל אותכם לשורה הבאה או משהו דומה לה:
;extension=php_mysqli.dll
יש להוריד את הנקודה-פסיק מתחילת השורה, לשמור את הקובץ
ולהפעיל מחדש את השרת.
II. התחברות ראשונה למסד
<?php
// Connecting to the database at
// localhost, with user: my_user, password: my_password, database: my_db
$mysqli = new mysqli('localhost', 'my_user', 'my_password', 'my_db');
// If there was an error during the connection - output it
if ($mysqli->connect_error)
die('Connect Error (' . $mysqli->connect_errno . ') ' . $mysqli->connect_error);
echo 'Successfully connected to ' . $mysqli->host_info ;
// Close the connection handler
$mysqli->close();
?>
// Connecting to the database at
// localhost, with user: my_user, password: my_password, database: my_db
$mysqli = new mysqli('localhost', 'my_user', 'my_password', 'my_db');
// If there was an error during the connection - output it
if ($mysqli->connect_error)
die('Connect Error (' . $mysqli->connect_errno . ') ' . $mysqli->connect_error);
echo 'Successfully connected to ' . $mysqli->host_info ;
// Close the connection handler
$mysqli->close();
?>
שימו לב, פונקציית החיבור למסד מקבלת ארבעה פרמטרים ולא שלושה.
הפרמטר הרביעי הוא שם המסד שאותו רשמנו בפונקציה mysql_select_db בעבר.
במידה ויש שגיאה כלשהי בהתחברות, php תציב ערכים כלשהם במאפיינים
connect_errno ו-connect_error של האובייקט.
אם ההתחברות הצליחה, במאפיין host_info יופיע שם שרת הmysql
שיהיה localhost במקרה שלנו.
בתום התהליך עלינו לשחרר את הזיכרון ולנתק את החיבור של php מהמסד.
חשוב לזכור לנתק את החיבור משני סיבות:
א. לפנות זכרון (למרות ש-php תעה זאת בעצמה מאוחר יותר)
ב. יש הגבלה על כמות חיבורים מקבילים למסד
III. שליפה עם mysqli
בואו נבצע את השאילתה SELECT NOW( ) באמצעות mysqli
השאילתה הזו צריכה להחזיר שורה אחת בלבד עם עמודה אחת בלבד בה.
<?php
$mysqli = new mysqli('localhost', 'my_user', 'my_password', 'my_db');
if ($mysqli->connect_error) die($mysqli->connect_error);
echo 'Successfully connected to ' . $mysqli->host_info ;
// mysqli->query creates a NEW OBJECT
//This object has it's own properties and methods
if ($result = $mysqli->query('SELECT NOW()'))
{
echo 'Mysql returned ',$result->num_rows, ' row with ', $result->field_count,' field';
// Mysql returned 1 row with 1 field
/* while ( $row = $result->fetch_row() ) echo "Now it's: ", row[0]; */
$row = $result->fetch_row();
echo "Now it's: ", $row[0];
/* free result set */
$result->close();
}
$mysqli->close();
?>
$mysqli = new mysqli('localhost', 'my_user', 'my_password', 'my_db');
if ($mysqli->connect_error) die($mysqli->connect_error);
echo 'Successfully connected to ' . $mysqli->host_info ;
// mysqli->query creates a NEW OBJECT
//This object has it's own properties and methods
if ($result = $mysqli->query('SELECT NOW()'))
{
echo 'Mysql returned ',$result->num_rows, ' row with ', $result->field_count,' field';
// Mysql returned 1 row with 1 field
/* while ( $row = $result->fetch_row() ) echo "Now it's: ", row[0]; */
$row = $result->fetch_row();
echo "Now it's: ", $row[0];
/* free result set */
$result->close();
}
$mysqli->close();
?>
mysqli->query יוצרת אובייקט חדש לחלוטין מסוג mysqli_result
עם מטודות ומאפיינים משלו.
לאחר שליפה, באמצעות לולאה נעבור על כל השורות ונוציא מהם את הערכים, כפי שעשינו עם mysql.
במקרה שלנו יש רק שורה אחת, לכן הלולאה תפעל רק פעם אחת.
לכן בעצם אין צורך בלולאה עצמה כלל.
ב-mysql יכולנו להשתמש בפונקציה mysql_result כדי לגשת לעמודה אחת בשורה אחת בלי לולאות ומערכים. ב-mysqli אין פונקציה זהה, לכן יהיה עלינו להשתמש באחת מפונקציות ה-fetch:
$result->fetch_row
$result->fetch_assoc
$result->fetch_array
$result->fetch_object
שיחרור תוצאות, MYSQLI_USE_RESULT or MYSQLI_STORE_RESULT
חשוב מאוד לשהתמש ב $result->close לאחר השאילתה כדי למחוק את תוצאות השליפה הקודמות. הצורך בא נובע מאופן בו נשמרים הנתונים הנשלפים.
mysqli->query מקבלת שני פרמטרים, הראשון הוא השאילתה שיש לבצע והשני הוא אופן השליפה. אופני השליפה נבדלים זה מזה באופן בו התוצאות נשמרות:
אפשרות ראשונה MYSQLI_STORE_RESULT היא שנשלוף את כל הנתונים מהמסד לזיכרון של php ונעבוד איתם מהזיכרון של php בלי שום קשר נוסף למסד.
האפשרות השניה, MYSQLI_USE_RESULT היא שנבצע את השאילתה, המסד יכין את רשימת התוצאות ויחזיר לנו רק את השורה הראשונה. לאחר שנעבוד עם השורה הראשונה — ייגש php שוב אל המסד ויקבל את השורה השניה מתוצאות המוכנות מראש (ללא ביצוע השאילתה פעם נוספת).
במידה ויש לנו כמות נתונים קטנה שניתן למקם את כולה בזיכרון, רצוי לשלוף את כל הנתונים פעם אחת באמצעות האופציה הראשונה ולעבוד איתה, כך שהעבודה עם המסד תהיה מהירה יותר (ללא גישה מרובה למסד).
במידה וכמות הנתונים ששלפנו גדולה, אין צורך להכניס את כולה לזיכרון ו-php ידאג לייבא את השורות מהמסד בהתאם.
מבחינת הקוד שלנו שני האפשרויות זהות לחלוטין וההבדל הוא רק בפרמטר השני של הפונקציה mysqli->query, כאשר מתחת לפני השטח php ידאג להביא את הנתונים מהמקום המתאים.
כאשר אנחנו משתמשים באפשרות השניה, של שמירת נתונים במסד יוצרת php חיבור מתמיד אל המסד עם מצביעים פנימיים שלה ושל המסד כדי לתאם עם המסד מהי השורה הבאה שצריך להחזיר מאיזה רשימת תוצאות.
במקרה הזה, אם ננסה לבצע שאילתה נוספת נתקל בשגיאה
Error: Commands out of sync; You can't run this command now
לכן עלינו ראשית למחוק את תוצאת השליפה הקודמת והקישוריות הזו בין php למסד ורק לאחר מכן להפעיל את השאילתה הבאה בעזרת $result->close()
IV. חיטוי נתונים
גם ב-mysqli יש לחטא את הנתונים לפני ההכנסה למסד.
האופן זהה מאוד ל-mysql
<?php
...
$city = " 'Yohansburg or 1=1 ";
$city = $mysqli->real_escape_string($city);
...
$city = " 'Yohansburg or 1=1 ";
$city = $mysqli->real_escape_string($city);
V. כתיבת מעטפת לנוחות מירבית
הרבה פעמים חוזרת הבדיקה האם ההתחברות הצליחה לאחר התחברות או חוזרים על עצמם חלקים אחרים של קוד. את אותו קוד ניתן להכניס למחלקה משלנו לעבודה עם המסד. לדוגמה באופן הבא:
<?php
class db extends mysqli
{
private $connected = false;
public function __construct($host, $user, $pass, $db, $charset)
{
parent::__construct($host, $user, $pass, $db);
if ($this->connect_error) die("Connection Error: ".$this->connect_error );
$this->set_charset($charset);
$this->connected = true;
}
public function query($query, $resultmode = MYSQLI_STORE_RESULT )
{
$res = parent::query($query, $resultmode);
if($res === false) die("SQL Error: ".$this->error );
return $res;
}
function __destruct() { if($this->connected) $this->close(); }
}
$mysqli = new db('localhost','my_user','my_password', 'my_db', 'utf8');
?>
class db extends mysqli
{
private $connected = false;
public function __construct($host, $user, $pass, $db, $charset)
{
parent::__construct($host, $user, $pass, $db);
if ($this->connect_error) die("Connection Error: ".$this->connect_error );
$this->set_charset($charset);
$this->connected = true;
}
public function query($query, $resultmode = MYSQLI_STORE_RESULT )
{
$res = parent::query($query, $resultmode);
if($res === false) die("SQL Error: ".$this->error );
return $res;
}
function __destruct() { if($this->connected) $this->close(); }
}
$mysqli = new db('localhost','my_user','my_password', 'my_db', 'utf8');
?>
המחלקה הזו מרחיבה את המחלקה mysqli הבסיסית ומוסיפה לה את בדיקת ההתחברות ובחירת קידוד בזמן ההתחברות, הודעה על שגיאות בשאילתות במידה ויהיו כאלו וסגירה אוטומטית של החיבור למסד בסוף הסקריפט.
ניתן להשתמש בזה על מנת להעביר את המשתמש לעמוד שגיאה ספציפי
או להוסיף פונקציונליות אחרת למעטפת במידת הצורך, כמו ניתור שגיאות.
זהו בסיס השימוש ב-MySQL Improved
שכוללת בין היתר אפשרויות נוספות שלא עמדנו עליהם בכתבה זו.
רוב המתכנתים עברו ל mysqli מאז הופעתה ב-PHP5
ואתה?
תגובות לכתבה:
יפה מאוד!!
כל הכבוד :)
very usefull small class
ראיתי גם שבמקום mysqli->num_rows וכל אלה, אפשר mysqli_num_rows..
כנ"ל גם לגבי fetch, mysqli_query וכו'...
האם יש הבדל בין השורות האלה? :
mysqli_query('SELECT NOW()')
mysqli->query('SELECT NOW()')
הדוגמה הראשונה היא שימוש בפונקציות של mysqli בתכנות פרוצדורלי, והשני זהו תכנות מונחה עצמים שיתאים לך יותר עם אתה עובד ב OOP
את זה אני הבנתי, השאלה היא האם יש הבדלי מהירות בינהם ויש דרך "עדיפה" מסיבה מסוימת.
לא. שניהם מבצעות את אותו הקוד מתחת לפני השטח.
הבחירה שלך צריכה להיות מטעמי נוחות.
תודה רבה, עזרת לי מאוד. :)
$mysqli = new mysqli($host, $user, $pass, $db);
if($mysqli->connect_error || $mysqli->connect_errno)
die('This is error.');
ברגע שאני מריץ את זה בWAMP והערכים שנשלחים למחלקה שגויים מלבד השרת (localhost) , נפלטת לי שגיאה מהמחלקה עצמה , אני לא מדבר על ה DIE.
מה לעשות ?
לטפוס את השגיאה.
אפ תשאל את זה דרך הפורום בצירוף הודעת השגיאה - אדע לעזור לך ביתר דיוק :)
קיימת טבלה שמציגה את המשתנים של MYSQL ושל MYSQLI בהשוואה ?
זה יעזור לי ממש.
אין טבלה, יש דוקומנטציה.
אם תנסה להשוות את mysqli לדברים אחרים זה לא ייתן לך הרבה. יש הרבה דברים שונים. תסתכל על זה בתור משהו חדש ולא קשור להרחבת mysql הרגילה. פשוט תלמד להישתמש ב mysqli מאפס וזהו.
מה עדיך יותר mysqli או PDO ?
אני כרגע עובד עם PDO יותר נוח לי איתו.
להשאר איתו או שיותר עדיף Mysqli ?
תישאר עם pdo ...